<?php
/**
 * Form_Select
 *
 * класс Form_Select позволяет работать с <select>
 * @author Дмитрий Кузьма <kouzma.d@gmail.com>
 * @version 1.1
 */
class Form_Select extends Form_Element
{
  protected $_optionsArray = array(); //Массив options
  protected $_optionsArrayForTop = array(); //Массив options для вывода вверху списка

  protected $_defaultString; //Строка, отображаемая по умолчанию в дополнение к массиву
  protected $_useSimpleArray = true; //Использовать ли упрощенный масссив
  protected $_keyName; //поле массива, из которого брать ключ для options
  protected $_valueName; //поле массива, из которого брать  значение для options
  protected $_optionClassName; //поле массива, из которого брать класс для options
  protected $_optionAttrsName; //поле массива, из которого брать атрибуты для options
  protected $_treeSelect = false; //древовидный селект
  protected $_treePrefix = '&nbsp;&nbsp;';
  protected $_chooseText = null; // Текст, который будет выводиться для выбора города
  protected $_multiple = false; // выводить мультиселект
  protected $_arrSelectedValue = array(); // выводить мультиселект

  function __construct(array $arrSettings = array(), $fieldName = null, $showInConstruct = false) {
    parent::__construct($arrSettings, $fieldName);
    if ($showInConstruct) $this->show();
  }
	/**
	 * Метод устанавливает свойство
	 *
	 * @param string $settingName
	 * @param mixed $settingValue
	 * @param string $additionalAllowedSettings
	 */
	public function setSetting($settingName, $settingValue, $additionalAllowedSettings = null) {
    switch ($settingName) {
    	case 'optionsArray':
    		$this->setOptionsArray($settingValue);
    		break;
      case 'chooseText':
        $this->_chooseText = $settingValue;
        break;
    	case 'optionsArrayForTop':
    		$this->setOptionsArrayForTop($settingValue);
    		break;
    	case 'keyName':
    		$this->setKeyName($settingValue);
    		break;
    	case 'valueName':
    		$this->setValueName($settingValue);
    		break;
    	case 'optionClassName':
    		$this->setOptionClassName($settingValue);
    		break;
    	case 'optionAttrsName':
    		$this->setOptionAttrsName($settingValue);
    		break;
    	case 'tree': case 'treeSelect':
    		$this->_treeSelect = $settingValue;
    		break;
    	case 'treePrefix':
    		$this->_treeSelect = true;
    		$this->_treePrefix = $settingValue;
    		break;
    	case 'multiple':
    		$this->_multiple = true;
    		break;
    	case 'selectedArray':
    		$this->_arrSelectedValue = $settingValue;
    		break;
    	default:
    	  parent::setSetting($settingName, $settingValue, '"optionsArray", "optionsArrayForTop", "keyName", "valueName"');
			  break;
    }
  }
  /**
   * задет массив для элементов options
   *
   * @param array $optionsArrayForTop
   */
  public function setOptionsArrayForTop($optionsArrayForTop) {
    $this->_optionsArrayForTop = $optionsArrayForTop;
  }
  /**
   * задет массив для элементов options, которые должны выводиться сверху
   *
   * @param array $optionsArray
   */
  public function setOptionsArray($optionsArray) {
    $this->_optionsArray = $optionsArray;
  }
  /**
   * задет название ключа, по которому заполнять значение <option value="!!!!!"
   *
   * @param string $keyName
   */
  public function setKeyName($keyName) {
    $this->_keyName = $keyName;
    $this->_useSimpleArray = false;
  }
  /**
   * задет название ключа, по которому заполнять значение <option>!!!!!</option>
   *
   * @param string $valueName
   */
  public function setValueName($valueName) {
    $this->_valueName = $valueName;
    $this->_useSimpleArray = false;
  }
  /**
   * Задает класс для <option>!!!!!</option>
   *
   * @param string $valueName
   */
  public function setOptionClassName($valueName) {
    $this->_optionClassName = $valueName;
  }
  /**
   * Задает ключ для массива с атрибутами для <option>!!!!!</option>
   *
   * @param string $valueName
   */
  public function setOptionAttrsName($valueName) {
    $this->_optionAttrsName = $valueName;
  }
  /**
   * Выводит элемент
   *
   */
  public function show() {
  	$this->checkForErrors();
  	
  	echo '<select';
  	$this->showElementAttributes();
  	if ($this->_multiple) echo ' multiple';
  	//if ($this->_required) echo ' required="required"';
  	echo '>';

  	if (isset($this->_value) && $this->_value != '') $selectedValue = $this->_value;
  	elseif (isset($this->_defaultValue)) $selectedValue = $this->_defaultValue;

  	if ($this->_chooseText !== null) echo '<option value="">' . $this->_chooseText . '</option>';
  	
		if (!$this->_useSimpleArray) {
			$this->showOptions($this->_optionsArrayForTop, $this->_keyName, $this->_valueName, $this->_optionClassName, $this->_optionAttrsName, $selectedValue);
			$this->showOptions($this->_optionsArray, $this->_keyName, $this->_valueName, $this->_optionClassName, $this->_optionAttrsName, $selectedValue);
		}
		else {
			$this->showSimpleOptions($this->_optionsArrayForTop, $selectedValue);
			$this->showSimpleOptions($this->_optionsArray, $selectedValue);
		}
  	echo '</select>';
  	$this->showAfterElementMessage();
  }
  
  /**
   * Выводит элемент
   *
   */
  public function showNew() {
  	$this->checkForErrors();
  
  	if (isset($this->_value) && $this->_value != '') $selectedValue = $this->_value;
  	elseif (isset($this->_defaultValue)) $selectedValue = $this->_defaultValue;
   
  	echo V_Form::select($this->_optionsArray, array('active' => $selectedValue, 'name' => $this->getName() . (!empty($this->_multiple) ? '[]' : null)));
  	$this->showAfterElementMessage();
  }

  /**
   * Выводит options
   *
   * @param array $arrOptions
   * @param string $keyName
   * @param string $valueName
   * @param mixed $selectedValue
   */
  public function showOptions(array $arrOptions, $keyName, $valueName, $optionClassName, $optionAttrsName, $selectedValue = -1, $curPrefix = '') {
  	$optionsSize = sizeof($arrOptions);
  	foreach ($arrOptions as $arrOption) {
  		echo '<option';
        if ($curPrefix != '') echo ' style="font-style:italic;"';
        echo ' value="' . $arrOption[$keyName] . '"';
      	if ($arrOption[$keyName] == $selectedValue || in_array($arrOption[$keyName], $this->_arrSelectedValue)) echo ' selected="selected"';
      	if ($optionClassName) echo ' class="' . $arrOption[$optionClassName] . '"';
      	if ($optionAttrsName && !empty($arrOption[$optionAttrsName])) {
      		foreach ($arrOption[$optionAttrsName] as $attr => $value) {
      			echo ' ' . $attr . '="' . $value . '"';
      		}
      	}
      echo '>';
      	echo $curPrefix;
      	echo $arrOption[$valueName];
      echo '</option>';
      if ($this->_treeSelect && isset($arrOptions[$i]['children']))
        $this->showOptions($arrOption['children'], $keyName, $valueName, $optionClassName, $selectedValue, ($curPrefix . $this->_treePrefix) );
    }
  }

  /**
   * Выводит options
   *
   * @param array $arrOptions
   * @param mixed $selectedValue
   */
  public function showSimpleOptions(array $arrOptions, $selectedValue = -1) {
  	$optionsSize = sizeof($arrOptions);
  	foreach ($arrOptions as $key => $value) {
      echo '<option value="' . $key . '"';
      if ($selectedValue == $key || in_array($key, $this->_arrSelectedValue))
        echo ' selected="selected"';
      echo '>' . $value . '</option>';

  	}
  }

  /**
   * Задет параметры массива. После этого уже не будет использоваться упрощенный вариант
   *
   * @param string $keyName
   * @param string $valueName
   */
  public function setArrayParametrs($keyName, $valueName) {
    $this->_useSimpleArray = false;
    $this->_keyName = $keyName;
    $this->_valueName = $valueName;
  }
}
?>